#pragma once
/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Foundation Framework Class Library
 * Version 2.00
 * 
 * Socket Option Base Class
 *      Provides a base, generic implementation for representing socket options.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
#include "stdafx.h"
#include "SafeSocketHandle.h"
#include "SocketOptionException.h"
#include "ISocketOption.h"

using namespace System;
using namespace System::Net;
using namespace System::Net::Sockets;
using namespace Adaptive;
using namespace Adaptive::Foundation;

namespace Adaptive
{
	namespace Network
	{
		namespace Sockets
		{
			/// <summary>
			/// Provides a base, generic implementation for representing socket options.
			/// </summary>
			generic<typename T>
			public ref class SocketOptionBase abstract : ClearableObjectBase, ISocketOption
			{
			protected:
				/*--------------------------------------------------------------------------------
				 * Constructor / Dispose / Destructor Methods
				 *------------------------------------------------------------------------------*/
				#pragma region Constructor / Dispose / Destructor Methods
				/// <summary>
				/// Initializes a new instance of the class.
				/// </summary>
				/// <param name="level">A <see cref="SocketOptionLevel"/> enumerated value indicating the option level.</param>
				/// <param name="name">A <see cref="SocketOptionName"/> enumerated value indicating the option name.</param>
				SocketOptionBase(SocketOptionLevel level, SocketOptionName name);
				/// <summary>
				/// Initializes a new instance of the class.
				/// </summary>
				/// <param name="level">A <see cref="SocketOptionLevel"/> enumerated value indicating the option level.</param>
				/// <param name="name">A <see cref="SocketOptionName"/> enumerated value indicating the option name.</param>
				/// <param name="value">The initial value for the socket option.</param>
				SocketOptionBase(SocketOptionLevel level, SocketOptionName name, T value);
				#pragma endregion

				/*--------------------------------------------------------------------------------
				 * Protected Methods
				 *------------------------------------------------------------------------------*/
				#pragma region Protected Methods
				/// <summary>
				/// Determines if the specified socket option level supports the specified socket option
				/// name.
				/// </summary>
				/// <returns>
				/// <b>true</b> if the socket option name is listed under the specified option level; 
				/// otherwise, <b>false</b>.
				/// </returns>
				static bool IsNameOptionValidForLevel(SocketOptionLevel level, SocketOptionName name);
				#pragma endregion

			public:
				/*--------------------------------------------------------------------------------
				 * Public Properties
				 *------------------------------------------------------------------------------*/
				#pragma region Public Properties
				/// <summary>
				/// Gets or sets the socket option level.
				/// </summary>
				/// <value>
				/// A <see cref="SocketOptionLevel"/> enumerated value indicating the socket option level.
				/// </value>
				property SocketOptionLevel Level { SocketOptionLevel get(); void set(SocketOptionLevel value); }
				/// <summary>
				/// Gets or sets the socket option name..
				/// </summary>
				/// <value>
				/// A <see cref="SocketOptionName"/> enumerated value indicating the socket option name.
				/// </value>
				virtual property SocketOptionName Name { SocketOptionName get(); void set(SocketOptionName value); } 
				/// <summary>
				/// Gets or sets the socket option value.
				/// </summary>
				/// <value>
				/// The value fore the specified option.
				/// </value>
				property T	Value { T get(); void set(T value); }
				#pragma endregion

			private:
				SocketOptionLevel		_optionLevel;
				SocketOptionName		_optionName;
				T						_value;
			};
		}
	}
}
